package logger

import (
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"os"
	"path/filepath"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
)

// LoggerConfig 日志配置结构体
type LoggerConfig struct {
	FileName    string `mapstructure:"file_name"`    // 日志文件名称
	LogDir      string `mapstructure:"log_dir"`      // 日志文件保存路径
	MaxBytes    int64  `mapstructure:"max_bytes"`    // 日志文件大小
	BackupCount uint   `mapstructure:"backup_count"` // 日志文件保留数量
	Level       string `mapstructure:"level"`        // 日志级别
}

var Log *logrus.Logger

// InitLogger 初始化日志记录器
func InitLogger(config *LoggerConfig) {

	Log = logrus.New()

	// 设置日志级别
	level, err := logrus.ParseLevel(config.Level)
	if err != nil {
		Log.SetLevel(logrus.InfoLevel) // 默认使用Info级别
	} else {
		Log.SetLevel(level)
	}

	// 设置日志格式为文本格式，并启用颜色
	Log.SetFormatter(&logrus.TextFormatter{
		FullTimestamp:   true,
		TimestampFormat: "2006-01-02 15:04:05",
		ForceColors:     true,
	})

	// 确保日志目录存在
	if err := os.MkdirAll(config.LogDir, 0755); err != nil {
		Log.Errorf("创建日志目录失败: %v", err)
		panic(err)
		return
	}

	// 设置日志文件分割
	logWriter, err := rotatelogs.New(
		filepath.Join(config.LogDir, config.FileName+".%Y%m%d%H.log"), // 按小时分割
		rotatelogs.WithRotationTime(time.Hour),                        // 每小时轮转一次
		rotatelogs.WithRotationSize(config.MaxBytes),                  // 按大小轮转
		rotatelogs.WithRotationCount(config.BackupCount),              // 保留的文件数量
	)
	if err != nil {
		Log.Errorf("配置日志文件失败: %v", err)
	}

	// 设置不同级别的日志输出到不同文件
	writerMap := lfshook.WriterMap{
		logrus.PanicLevel: logWriter,
		logrus.FatalLevel: logWriter,
		logrus.ErrorLevel: logWriter,
		logrus.WarnLevel:  logWriter,
		logrus.InfoLevel:  logWriter,
		logrus.DebugLevel: logWriter,
		logrus.TraceLevel: logWriter,
	}

	// 添加文件日志钩子
	Log.AddHook(lfshook.NewHook(
		writerMap,
		&logrus.JSONFormatter{
			TimestampFormat: "2006-01-02 15:04:05",
		},
	))

	// 同时输出到控制台
	Log.SetOutput(os.Stdout)

	Log.Info("初始化日志成功....")

}

// GinLogger 返回一个Gin的日志中间件
func GinLogger(logger *logrus.Logger) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 开始时间
		startTime := time.Now()

		// 处理请求
		c.Next()

		// 结束时间
		endTime := time.Now()

		// 执行时间
		latencyTime := endTime.Sub(startTime)

		// 请求方式
		reqMethod := c.Request.Method

		// 请求路由
		reqUri := c.Request.RequestURI

		// 状态码
		statusCode := c.Writer.Status()

		// 请求IP
		clientIP := c.ClientIP()

		// 日志格式
		logger.Infof("| %3d | %13v | %15s | %s | %s |",
			statusCode,
			latencyTime,
			clientIP,
			reqMethod,
			reqUri,
		)
	}
}
